import subprocess
import os
import time
import logging

# 创建日志记录器实例
logger = logging.getLogger(__name__)
# 配置日志级别为 INFO，即记录 INFO 及以上级别的日志
logging.basicConfig(level=logging.INFO)


class MultiDevice:
    """
    多设备管理类，用于处理 Appium 服务的启动和设备连接等操作
    主要功能包括启动指定端口的 Appium 服务、检查并释放端口等
    """
    def start_appium(self, port_number=4723):
        """
        启动 Appium 服务的入口方法
        先检查端口是否被占用并处理，再启动 Appium 服务
        :param port_number: Appium 服务监听的端口号，默认 4733
        """
        # 检查指定端口是否被占用，若占用则尝试释放
        self.__check_port(port_number)
        # 启动并连接到指定端口的 Appium 服务
        self.__connect_appium(port_number)

    def connect_devices(self):
        """
        设备连接方法（预留）
        用于实现多设备的连接和管理逻辑，目前未实现具体功能
        """
        pass

    def __connect_appium(self, port_number):
        """
        启动 Appium 服务的内部方法（私有方法）
        构建并执行启动命令，在指定端口上启动 Appium 服务
        :param port_number: Appium 服务监听的端口号
        """
        # 构建 Windows 系统下的 Appium 启动命令
        # -a 指定服务器地址为本地回环地址
        # -p 指定服务端口号
        # --session-override 允许覆盖已存在的会话
        win_start = f"appium -a 127.0.0.1 -p {port_number} --session-override"

        # 执行启动命令，通过 subprocess.Popen 开启新进程
        subprocess.Popen(
            win_start,
            shell=True,  # 使用 shell 执行命令
            stdout=True,  # 标准输出重定向
            stderr=subprocess.STDOUT,  # 标准错误输出合并到标准输出
        )

        # 等待 3 秒，确保 Appium 服务有足够时间启动
        time.sleep(3)

    def __check_port(self, port_number):
        """
        检查端口占用情况的内部方法（私有方法）
        若端口被占用，则尝试杀死占用该端口的进程
        :param port_number: 需要检查的端口号
        """
        try:
            # 执行 Windows 端口检查命令：查看指定端口的网络连接及进程ID
            # netstat -ano：显示所有连接和监听端口，包含进程ID
            # findstr :{port_number}：筛选出包含指定端口的记录
            # read().split("\n")[0]：读取结果并取第一行记录
            result = os.popen(f"netstat -ano | findstr :{port_number}").read().split("\n")[0]

            # 执行 Windows 进程杀死命令：强制终止占用端口的进程
            # taskkill /F /PID {pid}：/F 强制终止，/PID 指定进程ID
            os.system(f"taskkill /F /PID {result.split()[-1]}")
        except Exception as e:
            # 若执行过程中出现异常（通常是端口未被占用），记录日志
            logger.info(f"端口[{port_number}]未被占用")